﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using FIFP.Common;
using Telerik.Windows.Controls.ScheduleView;
using System.Collections.ObjectModel;
using Telerik.Windows.Controls;
using FIFP.DashBoard.Model;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using FIFP.DashBoard.Helper;
using System.Windows.Browser;
using FIFP.DashBoard.Views;
using FIFP.DashBoard.Converters;

namespace FIFP.DashBoard.ViewModel
{
    public class AppointmentVM : ViewModelCore
    {
        #region Variables
        private List<FIFPAppointment> appointments;
        private List<FIFPAppointment> filteredAppointments;
        private List<ResourceType> resourceTypes;
        private List<ResourceGroupDescription> groupTypes;
        private List<Resource> unitList;
        private bool isEditAppointment;
        private int visibleDays = 365;
        private Visibility navigationVisibility = Visibility.Collapsed;
        private string timerulerGroupStringLableFormat;
        private FixedTickProvider minorTickLength;
        private FixedTickProvider majorTickLength;
        private FixedTickProvider groupTickLength;
        public DateTime currentDate = new DateTime(DateTime.Now.Year, 1, 1);
        #endregion

        #region Properties
        public List<FIFPAppointment> Appointments
        {
            get { return appointments; }
            set
            {
                if (appointments != value)
                {
                    appointments = value;
                    OnPropertyChanged(() => this.Appointments);
                }
            }
        }

        public List<FIFPAppointment> FilteredAppointments
        {
            get { return filteredAppointments; }
            set
            {
                if (filteredAppointments != value)
                {
                    filteredAppointments = value;
                    OnPropertyChanged(() => this.FilteredAppointments);
                }
            }
        }

        public List<ResourceType> ResourceTypes
        {
            get { return resourceTypes; }
            set
            {
                if (resourceTypes != value)
                {
                    resourceTypes = value;
                    OnPropertyChanged(() => this.ResourceTypes);
                }
            }
        }

        public List<ResourceGroupDescription> GroupTypes
        {
            get { return groupTypes; }
            set
            {
                if (groupTypes != value)
                {
                    groupTypes = value;
                    OnPropertyChanged(() => this.GroupTypes);
                }
            }
        }

        public List<Resource> UnitList
        {
            get { return unitList; }
            set
            {
                if (unitList != value)
                {
                    unitList = value;
                    OnPropertyChanged(() => this.UnitList);
                }
            }
        }


        public bool IsEditAppointment
        {
            get { return isEditAppointment; }
            set
            {
                if (isEditAppointment != value)
                {
                    isEditAppointment = value;
                    OnPropertyChanged(() => this.IsEditAppointment);
                }
            }
        }

        public int VisibleDays
        {
            get { return visibleDays; }
            set
            {
                if (visibleDays != value)
                {
                    visibleDays = value;
                    OnPropertyChanged(() => this.VisibleDays);
                }
            }
        }


        public Visibility NavigationVisibility
        {
            get { return navigationVisibility; }
            set
            {
                if (navigationVisibility != value)
                {
                    navigationVisibility = value;
                    OnPropertyChanged(() => this.NavigationVisibility);
                }
            }
        }

        public string TimerulerGroupStringLableFormat
        {
            get { return timerulerGroupStringLableFormat; }
            set
            {
                if (timerulerGroupStringLableFormat != value)
                {
                    timerulerGroupStringLableFormat = value;
                    OnPropertyChanged(() => this.TimerulerGroupStringLableFormat);
                }
            }
        }

        public FixedTickProvider MinorTickLength
        {
            get { return minorTickLength; }
            set
            {
                if (minorTickLength != value)
                {
                    minorTickLength = value;
                    OnPropertyChanged(() => this.MinorTickLength);
                }
            }
        }

        public FixedTickProvider MajorTickLength
        {
            get { return majorTickLength; }
            set
            {
                if (majorTickLength != value)
                {
                    majorTickLength = value;
                    OnPropertyChanged(() => this.MajorTickLength);
                }
            }
        }

        public FixedTickProvider GroupTickLength
        {
            get { return groupTickLength; }
            set
            {
                if (groupTickLength != value)
                {
                    groupTickLength = value;
                    OnPropertyChanged(() => this.GroupTickLength);
                }
            }
        }

        private ObservableCollection<OverlapGroup> overlapGroups;
        public ObservableCollection<OverlapGroup> OverlapGroups
        {
            get { return overlapGroups; }
            set { SetPropertyValue(() => OverlapGroups, value, val => overlapGroups = val); }
        }

        public DateTime CurrentDate
        {
            get { return currentDate; }
            set { SetPropertyValue(() => CurrentDate, value, val => currentDate = val); }
        }

        private GroupDescriptionCollection resourceGroupTypes;
        public GroupDescriptionCollection ResourceGroupTypes
        {
            get { return resourceGroupTypes; }
            set { SetPropertyValue(() => ResourceGroupTypes, value, val => resourceGroupTypes = val); }
        }

        private ScheduleViewDragDropBehavior radScheduleViewDragDropBehavior = new ScheduleDragDropBehavior();
        public ScheduleViewDragDropBehavior RadScheduleViewDragDropBehavior
        {
            get { return radScheduleViewDragDropBehavior; }
            set { SetPropertyValue(() => RadScheduleViewDragDropBehavior, value, val => radScheduleViewDragDropBehavior = val); }
        }

        #endregion

        #region Commands

        private ICommand _DialogCommand;
        public ICommand DialogCommand
        {
            get
            {
                return _DialogCommand ??
                        (_DialogCommand = new RelayCommand<object>(ShowAppointmentDialog));
            }
        }

        private ICommand _AppointmentCreateCommand;
        public ICommand AppointmentCreateCommand
        {
            get
            {
                return _AppointmentCreateCommand ??
                        (_AppointmentCreateCommand = new RelayCommand<object>(AppointmentCreating));
            }
        }

        private ICommand _AppointmentEditingCommand;
        public ICommand AppointmentEditingCommand
        {
            get
            {
                return _AppointmentEditingCommand ??
                        (_AppointmentEditingCommand = new RelayCommand<object>(EditAppointment));
            }
        }

        private ICommand _AppointmentEditCommand;
        public ICommand AppointmentEditCommand
        {
            get
            {
                return _AppointmentEditCommand ??
                        (_AppointmentEditCommand = new RelayCommand<object>(SaveAppointment));
            }
        }

        private ICommand _AppointmentDeletingCommand;
        public ICommand AppointmentDeletingCommand
        {
            get
            {
                return _AppointmentDeletingCommand ??
                        (_AppointmentDeletingCommand = new RelayCommand<object>(DeletingAppointment));
            }
        }
        private ICommand _AppointmentDeleteCommand;
        public ICommand AppointmentDeleteCommand
        {
            get
            {
                return _AppointmentDeleteCommand ??
                        (_AppointmentDeleteCommand = new RelayCommand<object>(DeleteAppointment));
            }
        }

        private ICommand _GroupTypeResourceLoadCommand;
        public ICommand GroupTypeResourceLoadCommand
        {
            get
            {
                return _GroupTypeResourceLoadCommand ??
                        (_GroupTypeResourceLoadCommand = new RelayCommand<RadScheduleView>(MakeResourceGroups));
            }
        }

        private ICommand _AppointmentVisibleRangeCommand;
        public ICommand AppointmentVisibleRangeCommand
        {
            get
            {
                return _AppointmentVisibleRangeCommand ??
                        (_AppointmentVisibleRangeCommand = new RelayCommand<RadScheduleView>(AppointmentSelectionChanged));
            }
        }

        #endregion

        #region Constructor
        public AppointmentVM()
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                ServiceLocator.Get<ImportVM>().OnAppointmentDataCompleted += new EventHandler<CustomEventArgs<AppointmentGroup>>(AppointmentVM_OnAppointmentDataCompleted);
                ServiceLocator.Get<OverlapVM>().OnAppointmentDataCompleted += new EventHandler<CustomEventArgs<AppointmentGroup>>(AppointmentVM_OnAppointmentDataCompleted);
                ServiceLocator.Get<OptMngVM>().OnAppointmentDataCompleted += new EventHandler<CustomEventArgs<AppointmentGroup>>(AppointmentVM_OnAppointmentDataCompleted);
                ServiceLocator.Get<ShutdownMngVM>().OnAppointmentDataCompleted += new EventHandler<CustomEventArgs<AppointmentGroup>>(AppointmentVM_OnAppointmentDataCompleted);
                ServiceLocator.Get<FilterVM>().OnAppointmentDataCompleted += new EventHandler<CustomEventArgs<AppointmentGroup>>(AppointmentVM_OnAppointmentDataCompleted);
                ServiceLocator.Get<OverlapVM_New>().OnAppointmentDataCompleted += new EventHandler<CustomEventArgs<AppointmentGroup>>(AppointmentVM_OnAppointmentDataCompleted);
            }
        }

        void AppointmentVM_OnAppointmentDataCompleted(object sender, CustomEventArgs<AppointmentGroup> e)
        {
            if (e.Item != null)
            {
                Appointments = e.Item.Appointments;
                FilteredAppointments = e.Item.Appointments;
                ResourceTypes = e.Item.ResourceTypes;
                UnitList = e.Item.UnitList;
                InitializeScheduleViewData();
            }
        }


        private void MakeResourceGroups(RadScheduleView radView)
        {
            List<ResourceGroupDescription> result = new List<ResourceGroupDescription>();
            ResourceGroupDescription group1 = new ResourceGroupDescription();
            group1.ResourceType = "Unit";
            group1.ShowNullGroup = false;
            result.Add(group1);
            radView.GroupDescriptionsSource = result;
        }


        private void InitializeScheduleViewData()
        {
            CurrentDate = ServiceLocator.Get<FilterVM>().StartDate;
            VisibleDays = Convert.ToInt32(ServiceLocator.Get<FilterVM>().EndDate.Subtract(ServiceLocator.Get<FilterVM>().StartDate).TotalDays);
            this.MinorTickLength = new FixedTickProvider(new DateTimeInterval(0, 0, 1, 0));
            this.MajorTickLength = new FixedTickProvider(new DateTimeInterval(0, 0, 1, 0));
            this.GroupTickLength = new FixedTickProvider(new DateTimeInterval(0, 0, 1, 0));
            this.TimerulerGroupStringLableFormat = "{0:MMM,yyyy}";//{0:MM/dd}
        }

        private void ShowAppointmentDialog(object e)
        {
            ShowDialogEventArgs eventArgs = e as ShowDialogEventArgs;
            if (eventArgs.DialogViewModel is ConfirmDialogViewModel)
            {
                ConfirmDialogViewModel viewModel = eventArgs.DialogViewModel as ConfirmDialogViewModel;
                if (viewModel != null && viewModel.Appointments.Count() > 0)
                {
                    IOccurrence[] occurance = viewModel.Appointments as IOccurrence[];
                    if (occurance != null)
                    {
                        FIFPAppointment appointment = occurance[0] as FIFPAppointment;
                        if (appointment != null && !appointment.IsAppointmentDelete)
                            eventArgs.Cancel = true;
                    }
                }
            }
            else if (eventArgs.DialogViewModel is AppointmentDialogViewModel)
            {
                AppointmentDialogViewModel viewModel = eventArgs.DialogViewModel as AppointmentDialogViewModel;
                if (viewModel != null)
                {
                    Occurrence occurance = viewModel.Occurrence as Occurrence;
                    if (occurance != null)
                    {
                        FIFPAppointment appointment = occurance.Appointment as FIFPAppointment;
                        if (ServiceLocator.Get<MainPageVM>().IsLinkedSDChecked)
                        {
                            if (appointment != null && appointment.IsAppointmentDelete && appointment.IsLinkedShutdownPlan)
                                eventArgs.Cancel = true;
                        }
                        else if (ServiceLocator.Get<MainPageVM>().IsOverLapChecked)
                        {
                            if (appointment != null && appointment.IsAppliedSimops)
                                eventArgs.Cancel = true;
                        }
                    }
                }
            }

        }

        private void AppointmentCreating(object e)
        {
            AppointmentCreatingEventArgs eventArgs = e as AppointmentCreatingEventArgs;
            FIFPAppointment appointment = eventArgs.Appointment as FIFPAppointment;
            if (appointment != null)
            {
                appointment.IsDescEnabled = true;
            }
            /*if (eventArgs != null)        //Since We need to create appointment, we are disable this line.
                eventArgs.Cancel = true;*/

        }


        private void EditAppointment(object e)
        {
            AppointmentEditingEventArgs eventArgs = e as AppointmentEditingEventArgs;
            FIFPAppointment appointment = eventArgs.Appointment as FIFPAppointment;
            if (appointment != null)
            {
                appointment.Body = appointment.Division + "," + appointment.UnitType + "," + appointment.UnitName + "," + appointment.ActivityType;
                //appointment.IsSubjectEnabled = false;
                appointment.IsDescEnabled = false;
                IsEditAppointment = true;
            }
            else
            {
                if (appointment.Start == appointment.OriginalStart && appointment.End <= appointment.OriginalEnd)
                    eventArgs.Cancel = true;
            }

        }
        private void SaveAppointment(object e)
        {
            AppointmentEditedEventArgs eventArgs = e as AppointmentEditedEventArgs;
            FIFPAppointment appointment = eventArgs.Appointment as FIFPAppointment;
            if (appointment != null)
            {
                if (ServiceLocator.Get<MainPageVM>().IsLinkedSDChecked) //This is calling twice.
                {
                    foreach (FIFPAppointment activity in ServiceLocator.Get<ShutdownMngVM>().ActivityListWithSelectedUnit)
                    {
                        if (appointment.Equals(activity))
                        {
                            foreach (FIFPAppointment lsdPlan in activity.FilteredLsdPlans)
                            {
                                lsdPlan.Start = appointment.Start;
                                lsdPlan.End = appointment.End;
                            }
                            break;
                        }
                    }

                    if (ServiceLocator.Get<ShutdownMngVM>().ActivityListWithSelectedUnit != null && ServiceLocator.Get<ShutdownMngVM>().ActivityListWithSelectedUnit.Count > 0) //If we change the appointment start date and end date we have to update the same for linked shutdown plans
                    {

                        List<FIFPAppointment> lsdPlans = new List<FIFPAppointment>();
                        foreach (FIFPAppointment activity in ServiceLocator.Get<ShutdownMngVM>().ActivityListWithSelectedUnit)
                        {
                            lsdPlans.Add(activity);
                            lsdPlans.AddRange(activity.FilteredLsdPlans.Where(s => s.IsLinkedShutdownPlan == true));
                        }
                        FilteredAppointments = lsdPlans;
                    }
                }
                if (ServiceLocator.Get<MainPageVM>().IsOptMngChecked)
                {
                    List<FIFPAppointment> lsdChilds = ServiceLocator.Get<OptMngVM>().FilteredLinkedShutdownList.Where(s => s.UnitID == appointment.UnitID && s.IsLinkedShutdownPlan == true).ToList<FIFPAppointment>();
                    if (lsdChilds != null && lsdChilds.Count > 0)
                    {
                        foreach (FIFPAppointment appointmentItem in lsdChilds)
                        {
                            bool overlap = !(appointmentItem.End < appointment.Start || appointmentItem.Start > appointment.End);
                            if (overlap)
                            {
                                appointment.ModificationReason = "Activity optimized";
                                ServiceLocator.Get<OptMngVM>().OptimizedActivityList.Add(appointment);
                                break;
                            }
                            else
                            {
                                if (ServiceLocator.Get<OptMngVM>().OptimizedActivityList.Contains(appointment))
                                {
                                    appointment.ModificationReason = string.Empty;
                                    ServiceLocator.Get<OptMngVM>().OptimizedActivityList = new ObservableCollection<FIFPAppointment>(ServiceLocator.Get<OptMngVM>().OptimizedActivityList.Except(new List<FIFPAppointment>() { appointment }));
                                }
                            }

                        }
                        //isOverlap = !(planList[i + 1].End < planList[i].Start || planList[i + 1].Start > planList[i].End);
                    }
                }
                else
                {
                    if (appointment.Start != appointment.OriginalStart || appointment.End != appointment.OriginalEnd)
                        appointment.IsModified = true;
                }
            }
        }

        private void DeletingAppointment(object e)
        {

        }

        private void DeleteAppointment(object e)
        {
            AppointmentDeletedEventArgs eventArgs = e as AppointmentDeletedEventArgs;
            FIFPAppointment appointment = eventArgs.Appointment as FIFPAppointment;
            if (appointment != null && ServiceLocator.Get<MainPageVM>().IsLinkedSDChecked)
            {
                appointment.IsLinkedShutdownPlan = false;// TODO implement the linked SD delete logic and update that in original object too
            }
        }

        private void AppointmentSelectionChanged(RadScheduleView view)
        {

        }

        #endregion
    }
}
